package lockx

import (
	"sync"

	"github.com/gookit/color"
)

//Mutex 互斥鎖
//RWMutex 讀寫鎖

// 並發場景 -->數據競爭

//var mp sync.Map //原子操作加锁，读多写少+ key值已经存在->修改

type MutexP struct {
}

func (p MutexP) Single(size int) {
	mp := make(map[string]int)
	list := []string{"a", "b", "c", "d", "e"}
	for i := 0; i < size; i++ {
		for _, item := range list {
			_, ok := mp[item]
			if !ok {
				mp[item] = 0
			}
			mp[item] += 1
		}

	}
	color.Greenln(mp)

}

// fatal error: concurrent map read and map write
func (p MutexP) MSingle(size int) {
	mp := make(map[string]int)
	list := []string{"a", "b", "c", "d", "e"}
	wg := sync.WaitGroup{}
	for i := 0; i < size; i++ {
		wg.Add(1)
		// 直接使用协程操作会报错
		go func() {
			defer wg.Done()
			for _, item := range list {
				_, ok := mp[item]
				if !ok {
					mp[item] = 0
				}
				mp[item] += 1
			}
		}()
	}
	wg.Wait()
	color.Redln(mp)
}

// MSingleSafe 互斥
func (p MutexP) MSingleSafe(size int) {
	type safeMap struct {
		data map[string]int
		sync.Mutex
	}
	sm := safeMap{
		data:  make(map[string]int),
		Mutex: sync.Mutex{},
	}
	list := []string{"a", "b", "c", "d", "e"}
	wg := sync.WaitGroup{}
	for i := 0; i < size; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			sm.Lock()
			defer sm.Unlock()
			for _, item := range list {
				_, ok := sm.data[item]
				if !ok {
					sm.data[item] = 0
				}
				sm.data[item] += 1
			}
		}()

	}
	wg.Wait()
	color.Yellowln(sm.data)

}
func (p MutexP) MSingleInt(n int) {
	var data int
	for i := 0; i < 10*n; i++ {
		go func() {
			data++
		}()
	}
	color.Yellowln("MSingleInt", data)

}
func (p MutexP) MSingleIntSafe(n int) {
	type safeInt struct {
		data int
		sync.Mutex
	}
	sm := safeInt{
		data:  0,
		Mutex: sync.Mutex{},
	}
	wg := sync.WaitGroup{}
	for i := 0; i < n*10; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			sm.Lock()
			defer sm.Unlock()
			sm.data++
		}()

	}
	wg.Wait()
	color.Yellowln(sm.data)

}
